#ifndef _MY_DATA_
#define _MY_DATA_
#include<unordered_map>
#include<pthread.h>
#include"util.hpp"
#include"confg.hpp"
namespace cloud{
    struct BackupInfo{//文件备份信息结构体
        bool pack_flag;//压缩标志
        size_t fsize ; //文件大小
        time_t mtime ; //文件最后修改时间
        time_t atime ; //文件最后的访问时间
        std::string real_path; //文件的真实路径
        std::string pack_path; // 压缩包存储路径
        std::string url; //资源路径
        bool NewBackupInfo(const std::string &realpath ){//根据真实路径存储
            Config *config = Config::GetInstance();
            std::string packdir = config->GetPackDir();//压缩路径
            std::string packsuffix = config->GetPackFileSuffix();//后缀名
            std::string download_prefix = config->GetDownloadPrefix();//获取下载前缀
            FileUtil fu(realpath);
            if(fu.Exists() == false){
                std::cout<<"new backinfo file not exists!\n";
                return false;
            }
            this->pack_flag =false;
            this->fsize = fu.FileSize();
            this->mtime = fu.LastTime();
            this->atime = fu.LastATime();
            this->real_path = realpath;
            // ./backdir/a.txt -> ./packdir/a.txt.lz
            this->pack_path = packdir + fu.FileName() + packsuffix;
            // ./backdir/a.txt -> ./download/a.txt
            this->url = download_prefix + fu.FileName();
            return true;
        }
    };
    
    class DataManager{
        public:
            DataManager(){
                _backup_file = Config::GetInstance()->GetBackupFile();
                pthread_rwlock_init(& _rwlock , NULL);//读写锁初始化
                InitLoad();
            }

            ~DataManager(){
                pthread_rwlock_destroy(&_rwlock);
            }
            
            bool Insert(const BackupInfo &info){
                pthread_rwlock_wrlock(&_rwlock);//加写锁
                _table[info.url] = info;//加入
                pthread_rwlock_unlock(&_rwlock);//解锁
                Storage();
                return true;
            }//添加

            bool Update(const BackupInfo &info){
                 pthread_rwlock_wrlock(&_rwlock);//加写锁
                _table[info.url] = info;//修改
                pthread_rwlock_unlock(&_rwlock);//解锁
                Storage();
                return true;
            } //更新
           
            bool GetOneByURL(const std::string &url , BackupInfo *info){
                pthread_rwlock_wrlock(&_rwlock);//上锁
                auto it = _table.find(url);//根据url在hash表查找对应的info
                if(it == _table.end()){
                    return false;
                }
                *info = it->second;
                pthread_rwlock_unlock(&_rwlock);//解锁
                return true;
            }//根据url路径获取

            bool GetOneByRealPath(const std::string &realpath , BackupInfo *info){
                pthread_rwlock_wrlock(&_rwlock);//上锁
                auto it = _table.begin();
                for(; it!= _table.end() ; ++it){//遍历根据info中的realpath寻找
                    if(it->second.real_path == realpath){
                        *info = it->second;
                        return true;
                    }
                }
                pthread_rwlock_unlock(&_rwlock);//解锁
                return false;
            }//根据真实路径获取

            bool GetAll(std::vector<BackupInfo> *arry){
                pthread_rwlock_wrlock(&_rwlock);//上锁
                auto it = _table.begin();
                for(; it!= _table.end() ; ++it){//遍历根据info中的realpath寻找
                    arry->push_back(it->second);//将——table中的info全复制到arry
                }
                pthread_rwlock_unlock(&_rwlock);//解锁
                return false;
            }

            bool Storage(){//对文件进行持久化存储(每次有改变就需要进行一次)
                //1.获取所有数据
                std::vector<BackupInfo> arry;
                this->GetAll(&arry);
                //2.添加到json::value中
                Json::Value root;
                for(int i=0 ;i<arry.size() ; i++){
                    Json::Value item;
                    item["pack_flag"] = arry[i].pack_flag;
                    item["fsize"] = (Json::Int64)arry[i].fsize;
                    item["atime"] = (Json::Int64)arry[i].atime;
                    item["mtime"] = (Json::Int64)arry[i].mtime;
                    item["real_path"] = arry[i].real_path;
                    item["pack_path"] = arry[i].pack_path;
                    item["url"] = arry[i].url;
                    root.append(item);//添加数组元素
                }
                //3.序列化
                std::string body;
                JsonUtil::Serialize(root ,&body);
                //4.写文件
                FileUtil fu(_backup_file);
                fu.SetContent(body);//写入操作

                return true;
            }

            bool InitLoad(){
                //1.将数据读取出来
                FileUtil fu(_backup_file);
                if(fu.Exists() == false){
                    return false;
                }
                std::string body;
                fu.GetContent(&body);
                //2.反序列化
                Json::Value root;
                JsonUtil::UnSerialize(body, &root);
                //3.将反序列化得到的value数据添加到_table中
                for(int i=0 ; i<root.size() ; i++){
                    BackupInfo info;
                    info.pack_flag = root[i]["pack_flag"].asBool();
                    info.fsize = root[i]["fsize"].asInt64();
                    info.atime = root[i]["atime"].asInt64();
                    info.mtime = root[i]["mtime"].asInt64();
                    info.pack_path = root[i]["pack_path"].asString();
                    info.real_path= root[i]["real_path"].asString();
                    info.url = root[i]["url"].asString();
                    Insert(info);
                }
                return true;
            }//初始化程序运行时从文件读取数据
        private:
            std::string  _backup_file; //持久化文件存储数据（所有）
            pthread_rwlock_t  _rwlock; //读写锁--读共享，写互斥
            std::unordered_map<std::string , BackupInfo>  _table; //以hash表存储持久化文件
    };



}

#endif